package com.yeyks.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yeyks.dal.dao.*;
import com.yeyks.dal.domain.*;
import com.yeyks.exception.PermissionInvalidException;
import com.yeyks.exception.ServiceException;
import com.yeyks.exception.TokenInvalidException;
import com.yeyks.model.Ajax.AjaxResponseBody;
import com.yeyks.model.em.AccountType;
import com.yeyks.model.em.ResponseStatus;
import com.yeyks.service.AccountService;
import com.yeyks.service.OssService;
import com.yeyks.util.Utility;
import com.yeyks.exception.PermissionInvalidException;
import com.yeyks.exception.TokenInvalidException;
import com.yeyks.model.Ajax.AjaxResponseBody;
import com.yeyks.model.em.AccountType;
import com.yeyks.model.em.ResponseStatus;
import com.yeyks.service.AccountService;
import com.yeyks.service.OssService;
import com.yeyks.util.Utility;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import java.util.*;

@RestController
@Slf4j
@RequestMapping("/ajax")
public class UtilityController {
    @Autowired
    AccountService accountService;
    @Autowired
    OssService ossService;
    @Autowired
    AccountInfoMapper accountInfoMapper;

    @Autowired
    DocInfoMapper docInfoMapper;

    @Autowired
    ShareLogMapper shareLogMapper;

    @Autowired
    CouponInfoMapper couponInfoMapper;

    @Autowired
    UserCouponInfoMapper userCouponInfoMapper;

    /**
     * 设置文档
     * @param token
     * @param catalog
     * @param title
     * @param content
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/utility/setDoc", method = RequestMethod.POST)
    public ResponseEntity<?> setDoc(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "catalog", defaultValue = "", required = true) String catalog,
            @RequestParam(name = "title", defaultValue = "", required = true) String title,
            @RequestParam(name = "content", defaultValue = "", required = true) String content
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);

            String ossKey = "User/" + accountInfo.getId().toString() + "/doc/" + catalog + "/" + title;

            if (!ossService.writeOSS(content.getBytes("UTF-8"), ossKey)) {
                responseBody.setCode(ResponseStatus.RS_FAIL_OSS_ENGINE.getCode());
                responseBody.setMsg(ResponseStatus.RS_FAIL_OSS_ENGINE.getMsg());
                return ResponseEntity.ok(responseBody);
            }

            accountInfo.setExtraInfo(Utility.addExtraInfoMap(accountInfo.getExtraInfo(), "doc." + catalog, title, ossKey));
            int rec = accountInfoMapper.updateExtraInfoById(accountInfo.getId(), accountInfo.getExtraInfo());

            if (rec == 0) {
                throw new Exception("updated 0 row.");
            }

            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    /**
     * 获取文档
     * @param id
     * @param token
     * @param catalog
     * @param title
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/utility/getDoc", method = RequestMethod.POST)
    public ResponseEntity<?> getDoc(
            @RequestParam(name = "id", defaultValue = "", required = true) Integer id,
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "catalog", defaultValue = "", required = true) String catalog,
            @RequestParam(name = "title", defaultValue = "", required = true) String title
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            if (id == null || id == 0) {
                if (token != null && !token.isEmpty()) {
                    id = accountService.token2UserId(token);
                } else {
                    List<AccountInfo> accountInfoList = accountInfoMapper.selectByType(AccountType.Administrator);
                    if (accountInfoList.isEmpty()) {
                        throw new Exception("no admin account.");
                    }
                    id = accountInfoList.get(0).getId();
                }
            }

            String ossKey = "User/" + id.toString() + "/doc/" + catalog + "/" + title;
            byte [] byContent = ossService.readOSS(ossKey);
            String content = new String(byContent, "UTF-8");

            responseBody.setBody(content);
            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    /**
     * 查看文档列表（从账号）
     * @param id
     * @param token
     * @param catalog
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/utility/listDoc", method = RequestMethod.POST)
    public ResponseEntity<?> listDoc(
            @RequestParam(name = "id", defaultValue = "", required = true) Integer id,
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "catalog", defaultValue = "", required = true) String catalog
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = null;
            if (id == null || id == 0) {
                if (token != null && !token.isEmpty()) {
                    accountInfo = accountService.token2AccountInfo(token);
                } else {
                    List<AccountInfo> accountInfoList = accountInfoMapper.selectByType(AccountType.Administrator);
                    if (accountInfoList.isEmpty()) {
                        throw new Exception("no admin account.");
                    }
                    accountInfo = accountInfoList.get(0);
                }
            }

            JSONObject jsonObject = (JSONObject) JSON.parse(accountInfo.getExtraInfo());
            JSONObject cataObject = (JSONObject) jsonObject.get("doc." + catalog);

            List<String> titles = new ArrayList<>();
            for (String key : cataObject.keySet()) {
                titles.add(key);
            }

            responseBody.setBody(titles);
            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    @ApiIgnore
    @RequestMapping(value = "/utility/doc/add", method = RequestMethod.POST)
    public ResponseEntity<?> docAdd(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "id", defaultValue = "0", required = true) Integer id,
            @RequestParam(name = "caption", defaultValue = "false", required = true) String caption,
            @RequestParam(name = "content", defaultValue = "false", required = true) String content,
            @RequestParam(name = "parent", defaultValue = "0", required = true) Integer parent
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
            if (accountInfo.getType() != AccountType.Administrator &&
                    accountInfo.getType() != AccountType.BranchManager &&
                    accountInfo.getType() != AccountType.CityAgent) {
                throw new PermissionInvalidException();
            }

            List<DocInfo> origInfos = docInfoMapper.selectByCaption(caption);
            if (origInfos != null && origInfos.size() != 0 && id != origInfos.get(0).getId()) {
                throw new Exception("该标题已经存在");
            }

            DocInfo docInfo = new DocInfo();
            docInfo.setCaption(caption);
            docInfo.setContent(content);
            if (parent == 0) {
                docInfo.setDirectory(true);
            } else {
                DocInfo info = docInfoMapper.selectByPrimaryKey(parent);
                if (info == null || !info.getDirectory()) {
                    throw new Exception("parent is not directory");
                }
                docInfo.setParent(parent);
                docInfo.setDirectory(false);
            }

            int rec = 0;

            if (id == 0) {

                rec = docInfoMapper.insertReturnId(docInfo);
            } else {
                docInfo.setId(id);
                rec = docInfoMapper.updateCaptionContent(docInfo);
            }

            if (rec == 0) {
                throw new Exception("insert 0 row.");
            }

            responseBody.setBody(docInfo);
            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    /**
     * 获取文档列表
     * @param parent
     * @param keyword
     * @param pageNum
     * @param pageSize
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/utility/doc/list", method = RequestMethod.POST)
    public ResponseEntity<?> docList(
            @RequestParam(name = "parent", defaultValue = "0") Integer parent,
            @RequestParam(name = "keyword", defaultValue = "") String keyword,
            @RequestParam(name = "pageNum", defaultValue = "1") Integer pageNum,
            @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            Integer offset = null, maxrow = pageSize;

            if (pageNum != null && pageSize != null) {
                offset = (pageNum - 1) * pageSize;
            }

            List<Map> docInfoList;
            int count;
            if (parent == 0) {
                docInfoList = docInfoMapper.selectByDirectorKeyword(true, keyword, offset, maxrow);
                count = docInfoMapper.selectByDirectorKeywordCount(true, keyword);

            } else if (parent == -1) {
                docInfoList = docInfoMapper.selectByDirectorKeyword(false, keyword, offset, maxrow);
                count = docInfoMapper.selectByDirectorKeywordCount(false, keyword);
            } else {
                docInfoList = docInfoMapper.selectByParentKeyword(parent, keyword, offset, maxrow);
                count = docInfoMapper.selectByParentKeywordCount(parent, keyword);
            }

            responseBody.addMapBody("list", docInfoList);
            responseBody.addMapBody("count", count);

            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    /**
     * 文档删除
     * @param token
     * @param id
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/utility/doc/del", method = RequestMethod.POST)
    public ResponseEntity<?> docDel(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "id", defaultValue = "", required = true) Integer id
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
            if (accountInfo.getType() != AccountType.Administrator &&
                    accountInfo.getType() != AccountType.BranchManager &&
                    accountInfo.getType() != AccountType.CityAgent) {
                throw new PermissionInvalidException();
            }

            if (id == null || id == 0) {
                throw new Exception("id eq 0");
            }

            int rec = docInfoMapper.deleteById(id);
            if (rec == 0) {
                throw new Exception("insert 0 row.");
            }

            responseBody.setBody(rec);
            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    /**
     * 设置抽成比例
     * @param token
     * @param admin
     * @param branch
     * @param city
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/utility/precentage/set", method = {RequestMethod.POST, RequestMethod.GET})
    public ResponseEntity<?> precentageSet(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "admin", defaultValue = "0", required = true) Integer admin,
            @RequestParam(name = "branch", defaultValue = "0", required = true) Integer branch,
            @RequestParam(name = "city", defaultValue = "0", required = true) Integer city
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
            if (accountInfo.getType() != AccountType.Administrator) {
                throw new PermissionInvalidException();
            }

            accountService.setPrecentage(admin, branch, city);

            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    /**
     * 获取抽成比例
     * @param token
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/utility/precentage/get", method = {RequestMethod.POST, RequestMethod.GET})
    public ResponseEntity<?> precentageGet(
            @RequestParam(name = "token", defaultValue = "", required = true) String token
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
            if (accountInfo.getType() == AccountType.User) {
                throw new PermissionInvalidException();
            }

            Map pcInfo = accountService.getPrecentage();

            responseBody.setBody(pcInfo);
            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    /**
     * 分享
     * @param token
     * @param type
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/share/success", method = {RequestMethod.POST, RequestMethod.GET})
    public ResponseEntity<?> shareSuccess(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "type", defaultValue = "", required = true) String type
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
            if (accountInfo.getType() != AccountType.User) {
                throw new PermissionInvalidException();
            }

            ShareLog shareLog = new ShareLog();
            shareLog.setUserId(accountInfo.getId());
            shareLog.setShareType(type.toUpperCase());
            shareLog.setGmtCreate(new Date());
            shareLogMapper.insert(shareLog);

            List<CouponInfo> couponInfos = couponInfoMapper.selectAvailable(null, null);
            /*
            for (CouponInfo couponInfo : couponInfos) {

                UserCouponInfo userCouponInfo = new UserCouponInfo();
                userCouponInfo.setUserId(accountInfo.getId());
                userCouponInfo.setCouponId(id);
                userCouponInfo.setUsed(false);
                int rec = userCouponInfoMapper.insertReturnId(userCouponInfo);
                if (rec == 0) {
                    throw new Exception("inserted 0 row.");
                }
            }
            */

            responseBody.setBody(couponInfos);
            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    /**
     * 分享(3.0)
     *
     * @param token
     * @param type
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/share/successV2", method = {RequestMethod.POST, RequestMethod.GET})
    public ResponseEntity<?> shareSuccessV2(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "type", defaultValue = "", required = true) String type
    ) {

        UserInfo accountInfo = accountService.tokenUserInfo(token);
        ShareLog shareLog = new ShareLog();
        shareLog.setUserId(accountInfo.getId());
        shareLog.setShareType(type.toUpperCase());
        shareLog.setGmtCreate(new Date());
        int insert = shareLogMapper.insert(shareLog);
        if (insert != 1) {
            log.info("分享更新数据失败");
            throw new ServiceException("更新数据失败");
        }
        return ResponseEntity.ok(AjaxResponseBody.success());
    }

    /**
     * 根据指定条件查询分享数
     * @param token
     * @param type
     * @param gmtStart
     * @param gmtEnd
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/share/count", method = {RequestMethod.POST, RequestMethod.GET})
    public ResponseEntity<?> shareCount(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "type", defaultValue = "", required = true) String type,
            @RequestParam(name = "gmtStart", defaultValue = "", required = true) Long gmtStart,
            @RequestParam(name = "gmtEnd", defaultValue = "", required = true) Long gmtEnd
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
            if (accountInfo.getType() == AccountType.User) {
                throw new PermissionInvalidException();
            }

            Date dateStart = null, dateEnd = null;
            try {
                if (gmtStart != null) {
                    dateStart = new Date(gmtStart);
                }
                if (gmtEnd != null) {
                    dateEnd = new Date(gmtEnd);
                }
            } catch (Throwable e) {

            }

            int count = shareLogMapper.getCount(
                    dateStart, dateEnd, type.toUpperCase()
            );


            responseBody.setBody(count);
            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    /**
     * 获取各分享类型的数量
     * @param token
     * @param gmtStart
     * @param gmtEnd
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/share/countGbt", method = {RequestMethod.POST, RequestMethod.GET})
    public ResponseEntity<?> shareCountGbt(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "gmtStart", defaultValue = "", required = true) Long gmtStart,
            @RequestParam(name = "gmtEnd", defaultValue = "", required = true) Long gmtEnd
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
            if (accountInfo.getType() == AccountType.User) {
                throw new PermissionInvalidException();
            }

            Date dateStart = null, dateEnd = null;
            try {
                if (gmtStart != null) {
                    dateStart = new Date(gmtStart);
                }
                if (gmtEnd != null) {
                    dateEnd = new Date(gmtEnd);
                }
            } catch (Throwable e) {

            }

            List<Map> shareCounts = shareLogMapper.getCountGroupByType(
                    dateStart, dateEnd
            );

            responseBody.setBody(shareCounts);
            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }
}
